﻿/*************************************************************************************
 *
 * 文 件 名:   RFIDBUING
 * 描    述: 
 * 
 * 版    本：  V1.0
 * 创 建 者：  Naflim 
 * 创建时间：  2023/5/15 18:42:24
 * ======================================================
 * 历史更新记录
 * 版本： V          修改时间：         修改人：
 * 修改内容：
 * ======================================================
*************************************************************************************/

using AccessDoorPolice.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AccessDoorPolice.Reader
{
    public class RFIDBUING
    {
        object lof = new object();
        public ReaderType Conformitiesmethod(RfidType rfidType, RFID rfid, int LampType = 0)
        {
            lock (lof)
            {
                ReaderType readerType = null;
                try
                {
                    switch (rfidType)
                    {
                        case RfidType.Open:
                            readerType = Open(rfid);
                            break;
                        case RfidType.Close:
                            readerType = Close(rfid);
                            break;
                        case RfidType.Inventory_G2:
                            readerType = Inventory_G2(rfid, LampType);
                            break;
                        case RfidType.GetGPIOStatus:
                            readerType = GetGPIOStatus(rfid);
                            break;
                        case RfidType.SetGPIO:
                            readerType = SetGPIO(rfid, LampType);
                            break;
                        case RfidType.ReConnDisconnected:
                            readerType = ReConnDisconnected(rfid);
                            break;
                        case RfidType.SetAnt:
                            readerType = SetAnt(rfid);
                            break;
                        case RfidType.SetPower:
                            readerType = SetPower(rfid);
                            break;
                    }

                }
                catch (Exception ex)
                {
                    AppLog.Error(ex.Message);
                }
                return readerType;
            }
        }
        public ReaderType Open(RFID rfid)
        {
            ReaderType readerType;
            int linkflag;
            byte ComAdr = rfid.ComAdr;
            int FrmPort = rfid.FrmPort;

            linkflag = RWDev.OpenNetPort(rfid.Port, rfid.IP, ref ComAdr, ref FrmPort);
            if (linkflag == 0)
            {
                rfid.ComAdr = ComAdr;
                rfid.FrmPort = FrmPort;
                return readerType = new ReaderType(linkflag, null, "成功", 0);
            }
            string Mess = GetReturnCodeDesc(linkflag);
            return readerType = new ReaderType(linkflag, null, Mess, 0);
        }
        public ReaderType Close(RFID rfid)
        {
            ReaderType readerType;
            int linkflag;
            linkflag = RWDev.CloseNetPort(rfid.FrmPort);
            if (linkflag == 0)
            {
                return readerType = new ReaderType(linkflag, null, "成功", 0);
            }
            string Mess = GetReturnCodeDesc(linkflag);
            return readerType = new ReaderType(linkflag, null, Mess, 0);
        }
        public ReaderType GetGPIOStatus(RFID rfid)
        {
            ReaderType readerType;
            byte OutputPin = 0;
            byte ComAdr = rfid.ComAdr;
            int linkflag;

            linkflag = RWDev.GetGPIOStatus(ref ComAdr, ref OutputPin, rfid.FrmPort);

            if (linkflag == 0)
            {
                return readerType = new ReaderType(linkflag, null, "成功", OutputPin);
            }
            string Mess = GetReturnCodeDesc(linkflag);
            return readerType = new ReaderType(linkflag, null, Mess, 0);
        }
        public ReaderType SetGPIO(RFID rfid, int LampType)
        {
            ReaderType readerType;
            int linkflag;
            byte OutputPin = 0;
            byte ComAdr = rfid.ComAdr;
            int FrmPort = rfid.FrmPort;

            if (LampType == 1)
            {
                OutputPin = Convert.ToByte(OutputPin | 0x01);
            }
            else if (LampType == 2)
            {
                OutputPin = Convert.ToByte(OutputPin | 0x02);
            }
            linkflag = RWDev.SetGPIO(ref ComAdr, OutputPin, FrmPort);

            if (linkflag == 0)
            {
                return readerType = new ReaderType(linkflag, null, "", OutputPin);
            }
            string Mess = GetReturnCodeDesc(linkflag);
            return readerType = new ReaderType(linkflag, null, Mess, 0);
        }
        public ReaderType Inventory_G2(RFID rfid, int LampType)
        {
            ReaderType readerType;
            if (LampType == 0)
            {
                return readerType = Inventory(rfid);
            }
            else
            {
                return readerType = InventoryTIME(rfid, LampType);
            }
        }
        public ReaderType Inventory(RFID rfid)
        {
            ReaderType readerType;
            List<string> listEPC = new List<string>();
            int linkflag = 0;
            try
            {
                foreach (int item in rfid.Antennas)
                {
                    if (item == 0)
                    {
                        continue;
                    }
                    byte InAnt = (byte)item;
                    byte FastFlag = 1;//不可变
                    byte Qvalue = 4;//可变
                    byte tidAddr = 0;//可变
                    byte tidLen = 0;//可变
                    byte TIDFlag = 0;//可变
                    byte Scantime = 20;//可变
                    byte Target = 0;
                    byte Ant = 0;
                    byte MaskMem = 0;
                    byte MaskLen = 0;
                    byte MaskFlag = 0;
                    byte Session = 0;
                    byte[] MaskAdr = new byte[2];
                    byte[] MaskData = new byte[100];
                    byte[] EPC = new byte[50000];
                    int TagNum = 0;
                    int Totallen = 0;
                    byte ComAdr = rfid.ComAdr;
                    linkflag = RWDev.Inventory_G2(ref ComAdr, Qvalue, Session, MaskMem, MaskAdr, MaskLen, MaskData, MaskFlag, tidAddr, tidLen, TIDFlag, Target, InAnt, Scantime, FastFlag, EPC, ref Ant, ref Totallen, ref TagNum, rfid.FrmPort);
                    if (linkflag != 0x01 && linkflag != 0x02)
                    {
                        continue;
                    }
                    string[] EPCarr = GetEPC(EPC);
                    string[] epc = EPCarr.Where(str => str != null).ToArray().Distinct().ToArray();
                    foreach (string ESE in epc)
                    {
                        listEPC.Add(ESE);
                    }
                }
                listEPC = listEPC.Where(str => str != null).Distinct().ToList();
                if (linkflag != 0)
                {
                    string Mess = GetReturnCodeDesc(linkflag);
                    return readerType = new ReaderType(linkflag, listEPC, Mess, 0);
                }
                else
                {
                    return readerType = new ReaderType(linkflag, listEPC, "成功", 0);
                }
            }
            catch (Exception ex)
            {
                AppLog.Error($"设备{rfid.IP},天线{rfid.Antennas}查询出错,原因：{ex.Message}");
                return readerType = new ReaderType(linkflag, listEPC, "失败", 0);
            }

        }
        public ReaderType InventoryTIME(RFID rfid, int LampType)
        {
            ReaderType readerType;
            List<string> listEPC = new List<string>();
            int linkflag = 0;
            DateTime dateTime = DateTime.Now;
            try
            {
                while (DateTime.Now < dateTime.AddSeconds(LampType))
                {
                    foreach (int item in rfid.Antennas)
                    {
                        if (item == 0)
                        {
                            continue;
                        }
                        byte InAnt = (byte)item;
                        byte FastFlag = 1;//不可变
                        byte Qvalue = 4;//可变
                        byte tidAddr = 0;//可变
                        byte tidLen = 0;//可变
                        byte TIDFlag = 0;//可变
                        byte Scantime = 20;//可变
                        byte Target = 0;
                        byte Ant = 0;
                        byte MaskMem = 0;
                        byte MaskLen = 0;
                        byte MaskFlag = 0;
                        byte Session = 0;
                        byte[] MaskAdr = new byte[2];
                        byte[] MaskData = new byte[100];
                        byte[] EPC = new byte[50000];
                        int TagNum = 0;
                        int Totallen = 0;
                        byte ComAdr = rfid.ComAdr;
                        linkflag = RWDev.Inventory_G2(ref ComAdr, Qvalue, Session, MaskMem, MaskAdr, MaskLen, MaskData, MaskFlag, tidAddr, tidLen, TIDFlag, Target, InAnt, Scantime, FastFlag, EPC, ref Ant, ref Totallen, ref TagNum, rfid.FrmPort);
                        if (linkflag != 0x01 && linkflag != 0x02)
                        {
                            continue;
                        }
                        string[] EPCarr = GetEPC(EPC);
                        string[] epc = EPCarr.Where(str => str != null).ToArray().Distinct().ToArray();
                        foreach (string ESE in epc)
                        {
                            listEPC.Add(ESE);
                        }
                    }
                }
                listEPC = listEPC.Where(str => str != null).Distinct().ToList();
                if (linkflag != 0)
                {
                    string Mess = GetReturnCodeDesc(linkflag);
                    return readerType = new ReaderType(linkflag, listEPC, Mess, 0);
                }
                else
                {
                    return readerType = new ReaderType(linkflag, listEPC, "成功", 0);
                }
            }
            catch (Exception ex)
            {
                AppLog.Error($"设备{rfid.IP},天线{rfid.Antennas}查询出错,原因：{ex.Message}");
                return readerType = new ReaderType(linkflag, listEPC, "失败", 0);
            }

        }
        public ReaderType ReConnDisconnected(RFID rfid)
        {
            AppLog.Error($"设备{rfid.IP},已断开");
            ReaderType readerType = Conformitiesmethod(RfidType.Close, rfid);
            if (readerType.StatusCode == 0)
            {
                do
                {
                    readerType = Conformitiesmethod(RfidType.Open, rfid);
                    if (readerType.StatusCode == 0)
                    {
                        break;
                    }
                    Thread.Sleep(10000);
                } while (true);
            }
            AppLog.Error($"设备{rfid.IP},重连成功");
            return readerType;

        }
        public ReaderType SetAnt(RFID rfid)
        {
            ReaderType readerType;
            try
            {
                int linkflag = 0;
                byte ComAdr = rfid.ComAdr;
                int FrmPort = rfid.FrmPort;

                byte ANT = 0;
                List<int> list = new List<int>();

                for (int i = 0; i < rfid.Antennas.Count; i++)
                {
                    switch (rfid.Antennas[i])
                    {
                        case 1:
                            ANT = Convert.ToByte(ANT | 1);
                            list.Add(1);
                            break;
                        case 2:
                            ANT = Convert.ToByte(ANT | 2);
                            list.Add(2);
                            break;
                        case 3:
                            ANT = Convert.ToByte(ANT | 4);
                            list.Add(3);
                            break;
                        case 4:
                            ANT = Convert.ToByte(ANT | 8);
                            list.Add(4);
                            break;
                    }
                }
                rfid.Antennas.Clear();
                for (int j = 0; j < list.Count; j++)
                {
                    switch (list[j])
                    {
                        case 1:
                            rfid.Antennas.Add(0x80);
                            break;
                        case 2:
                            rfid.Antennas.Add(0x81);
                            break;
                        case 3:
                            rfid.Antennas.Add(0x82);
                            break;
                        case 4:
                            rfid.Antennas.Add(0x83);
                            break;
                    }
                }
                linkflag = RWDev.SetAntennaMultiplexing(ref ComAdr, ANT, FrmPort);
                if (linkflag == 0)
                {
                    return readerType = new ReaderType(linkflag, null, "成功", 0);
                }
                else
                {
                    string str = GetReturnCodeDesc(linkflag);
                    AppLog.Error($"设置天线出错原因是：{str}");
                    return readerType = new ReaderType(linkflag, null, str, 0);
                }
            }
            catch (Exception ex)
            {
                AppLog.Error($"设置天线出错原因是：{ex.Message}");
                return readerType = new ReaderType(1, null, "ex.Message", 0);
            }
        }
        public ReaderType SetPower(RFID rfid)
        {
            ReaderType readerType;
            try
            {
                int linkflag = 0;
                byte ComAdr = rfid.ComAdr;
                int FrmPort = rfid.FrmPort;
                byte[] powerDbm = new byte[4];
                foreach (Powerlist item in rfid.Powerlist)
                {
                    if (item.Ant == "1")
                    {
                        powerDbm[0] = Convert.ToByte(item.Power, 10);
                    }
                    if (item.Ant == "2")
                    {
                        powerDbm[1] = Convert.ToByte(item.Power, 10);
                    }
                    if (item.Ant == "3")
                    {
                        powerDbm[2] = Convert.ToByte(item.Power, 10);
                    }
                    if (item.Ant == "4")
                    {
                        powerDbm[3] = Convert.ToByte(item.Power, 10);
                    }
                }
                linkflag = RWDev.SetRfPowerByAnt(ref ComAdr, powerDbm, FrmPort);
                if (linkflag == 0)
                {
                    return readerType = new ReaderType(linkflag, null, "成功", 0);
                }
                else
                {
                    string str = GetReturnCodeDesc(linkflag);
                    AppLog.Error($"设置功率出错原因是：{str}");
                    return readerType = new ReaderType(linkflag, null, str, 0);
                }
            }
            catch (Exception ex)
            {
                AppLog.Error($"设置功率出错原因是：{ex.Message}");
                return readerType = new ReaderType(1, null, ex.Message, 0);
            }
        }
        public string GetReturnCodeDesc(int cmdRet)
        {
            switch (cmdRet)
            {
                case 0x00:
                case 0x26:
                    return "操作成功";
                case 0x01:
                    return "询查时间结束前返回";
                case 0x02:
                    return "指定的询查时间溢出";
                case 0x03:
                    return "本条消息之后，还有消息";
                case 0x04:
                    return "读写模块存储空间已满";
                case 0x05:
                    return "访问密码错误";
                case 0x09:
                    return "销毁密码错误";
                case 0x0a:
                    return "销毁密码不能为全0";
                case 0x0b:
                    return "电子标签不支持该命令";
                case 0x0c:
                    return "对该命令，访问密码不能为全0";
                case 0x0d:
                    return "电子标签已经被设置了读保护，不能再次设置";
                case 0x0e:
                    return "电子标签没有被设置读保护，不需要解锁";
                case 0x10:
                    return "有字节空间被锁定，写入失败";
                case 0x11:
                    return "不能锁定";
                case 0x12:
                    return "已经锁定，不能再次锁定";
                case 0x13:
                    return "参数保存失败,但设置的值在读写模块断电前有效";
                case 0x14:
                    return "无法调整";
                case 0x15:
                    return "询查时间结束前返回";
                case 0x16:
                    return "指定的询查时间溢出";
                case 0x17:
                    return "本条消息之后，还有消息";
                case 0x18:
                    return "读写模块存储空间已满";
                case 0x19:
                    return "电子不支持该命令或者访问密码不能为0";
                case 0x1A:
                    return "标签自定义功能执行错误";
                case 0xF8:
                    return "检测天线错误";
                case 0xF9:
                    return "命令执行出错";
                case 0xFA:
                    return "有电子标签，但通信不畅，无法操作";
                case 0xFB:
                    return "无电子标签可操作";
                case 0xFC:
                    return "电子标签返回错误代码";
                case 0xFD:
                    return "命令长度错误";
                case 0xFE:
                    return "不合法的命令";
                case 0xFF:
                    return "参数错误";
                case 0x30:
                    return "通讯错误";
                case 0x31:
                    return "CRC校验错误";
                case 0x32:
                    return "返回数据长度有错误";
                case 0x33:
                    return "通讯繁忙，设备正在执行其他指令";
                case 0x34:
                    return "繁忙，指令正在执行";
                case 0x35:
                    return "端口已打开";
                case 0x36:
                    return "端口已关闭";
                case 0x37:
                    return "无效句柄";
                case 0x38:
                    return "无效端口";
                case 0xEE:
                    return "命令代码错误";
                default:
                    return Convert.ToString(cmdRet, 16);
            }
        }
        public string[] GetEPC(byte[] bytes)
        {
            string[] array = new string[1000];
            Grouping(array, bytes, 0, 0);
            return array;
        }
        public static void Grouping(string[] strarr, byte[] byarr, int index, int count)
        {
            byte[] array = new byte[byarr[index]];
            if (byarr[index] != 0 && array.Length >= byarr[index])
            {
                int num = index + 1;
                int num2 = 0;
                while (num <= index + byarr[index])
                {
                    array[num2] = byarr[num];
                    num++;
                    num2++;
                }

                strarr[count] = ByteToHexStr(array);
                count++;
                Grouping(strarr, byarr, index + byarr[index] + 2, count);
            }
        }
        private static string ByteToHexStr(byte[] bytes)
        {
            string text = null;
            if (bytes != null)
            {
                for (int i = 0; i < bytes.Length; i++)
                {
                    text += bytes[i].ToString("X2");
                }
            }
            return text;
        }
    }
}
